import router from './index'
import { useUserStore } from '../store'
import NProgress from 'nprogress' // 引入nprogress插件
import 'nprogress/nprogress.css'  // 这个nprogress样式必须引入
import NotFound from '../views/NotFound.vue'

// 放行的路由
const whiteList = ['/login']

// 动态添加路由
const addRoutes = (routes, parantName = '') => {
    routes.forEach(route => {
        if (parantName === '') {
            router.addRoute(route)
        } else {
            if(router.hasRoute(parantName)){
                // 多个子路由的path前面不能有/
                route.path = route.path.substr(1)
                router.addRoute(parantName, route)
            }
        }
        if (route.children && route.children.length > 1) {
            addRoutes(route.children, route.name)
        }
    })
}

// 路由前置拦截
router.beforeEach(async (to, from, next) => {
    NProgress.start() // 设置加载进度条(开始..)
    const userStore = useUserStore()
    const { token } = userStore
    // 有token说明已经登录了
    if (token) {
        if (to.path === '/login') {
            // 已经登录如果再访问 /login 就跳转到首页
            next({ path: '/' })
            NProgress.done()
        } else {
            // 已经登录但是不是访问 /login 从pinia中获取权限信息
            if (to.name && userStore.hasRoles()) {
                // 有权限直接放行
                next()
            } else {
                // 不存在就需要从后台获取用户(权限)信息
                // 动态获取菜单信息,生成动态路由
                const notFoundPath = { path: '/:pathMatch(.*)*', name: 'NotFound', component: NotFound }
                const accessRoutes = await userStore.generateRoutes()
                // 保存动态菜单
                userStore.saveMenuList(accessRoutes)
                // 404页面最后添加
                accessRoutes.push(notFoundPath)
                // 动态添加
                addRoutes(accessRoutes)
                // 动态添加路由后需要重定向一次,因为原来的访问路由可能是不存在的动态添加后才会存在
                next({ ...to, replace: true })
            }
        }
    } else {
        if (whiteList.includes(to.path)) {
            next()
        } else {
            next('/login')
        }
    }
})

router.afterEach(() => {
    NProgress.done() // 设置加载进度条(结束..)
})